﻿using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Net;


namespace WindowsFormsApp1
{

    public partial class Form1 : Form
    {

        string ProgramFileBUF1, ProgramFileBUF2, BootloaderBUF, BootloaderBUF_CP, IPSW1_BUF, IPSW2_BUF;
        string bootNowNameBUF, IniReaderBUF;
        byte[] ProgramBinBUF = new byte[10240];//串口升级程序文件缓存文件最大10k

        SerialPort sp1 = new SerialPort();        //这个是定义的全局变量；

        private static List<byte> SerialBuffer = new List<byte>(10240);//串口接收数据缓存

        private static byte[] array = new byte[10];//返回命令缓冲

        private static readonly object locker = new object();//用于给list加锁

        Int16 updateTime = 0;//程序升级计时
        Int16 updateStep = 0;//程序升级步骤
        Int16 frameLength = 0;//程序帧发送数据长度


        Int32 PrgSendNum = 0;//帧发送次数
        Int32 PrgSendSum = 0;//当前发送帧数
        Int32 ComInterval = 5;//命令间隔,默认500ms

        Int32 RebootTime = 0;//手动复位等待时间


        public Form1()
        {
            InitializeComponent();
        }

        [DllImport("kernel32.dll")]
        private static extern int GetPrivateProfileString(string section, string key, string def, byte[] retVal, int size, string filePath);


        private void uiButton1_Click(object sender, EventArgs e)//bootloader
        {
            OpenFileDialog fileDialog1 = new OpenFileDialog();
            fileDialog1.Filter = "文本文件|*.hex";
            fileDialog1.RestoreDirectory = false;    //若为false，则打开对话框后为上次的目录。若为true，则为初始目录
            if (fileDialog1.ShowDialog() == DialogResult.OK)
                uiTextBox1.Text = System.IO.Path.GetFullPath(fileDialog1.FileName);//将选中的文件的路径传递给TextBox “FilePath”

            //读取boot到缓存
            try
            {
                //将boot文件读入缓存
                StreamReader FileBootloader = new StreamReader(uiTextBox1.Text, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                BootloaderBUF = FileBootloader.ReadToEnd();//读取program文件
                FileBootloader.Close();//关闭文件
                FileBootloader.Dispose();//释放缓存

                uiTextBox2.Text = Path.GetFileName(uiTextBox1.Text);//文件名
                uiTextBox4.Text = BootloaderBUF.Length.ToString();//长度

                uiTextBox5.Text = "0x" + BootloaderBUF.Substring((BootloaderBUF.IndexOf(":02") + 9), 4)
                                + BootloaderBUF.Substring((BootloaderBUF.IndexOf(":10") + 3), 4);//首地址

                uiTextBox3.Text = "0x" + BootloaderBUF.Substring((BootloaderBUF.IndexOf(":00") - 12), 8);//入口地址

            }
            catch
            {
                BootloaderBUF = null;
                MessageBox.Show("无法读取Bootloader！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void uiCheckBox2_ValueChanged(object sender, bool value)//固件2完整性标志
        {
            try
            {
                //将IPSW1文件读入缓存
                StreamReader FileIPSW2 = new StreamReader("./IPSW2_INFO.HEX", System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                IPSW2_BUF = FileIPSW2.ReadToEnd();//读取program文件
                FileIPSW2.Close();//关闭文件
                FileIPSW2.Dispose();//释放缓存
            }
            catch
            {
                IPSW2_BUF = null;
                MessageBox.Show("无法读取固件2信息文件！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string[] str = SerialPort.GetPortNames();//检查是否含有串口 
            if (str == null)
            {
                MessageBox.Show("本机没有串口！", "Error");
                return;
            }

            foreach (string s in System.IO.Ports.SerialPort.GetPortNames())   //添加串口
            {
                cbSerial.Items.Add(s);          //获取有多少个COM口，添加到控件里
            }
            cbSerial.SelectedIndex = 0; //设置默认串口号

            cbBaudRate.Items.Add("1200"); //设置波特率
            cbBaudRate.Items.Add("2400"); //设置波特率
            cbBaudRate.Items.Add("4800"); //设置波特率
            cbBaudRate.Items.Add("9600"); //设置波特率
            cbBaudRate.Items.Add("19200"); //设置波特率
            cbBaudRate.Items.Add("38400"); //设置波特率
            cbBaudRate.Items.Add("57600"); //设置波特率
            cbBaudRate.Items.Add("115200"); //设置波特率
            cbBaudRate.Items.Add("128000"); //设置波特率
            cbBaudRate.Items.Add("256000"); //设置波特率
            cbBaudRate.SelectedIndex = 3;//设置默认端口号为9600

            cbDataBits.Items.Add("5");
            cbDataBits.Items.Add("6");
            cbDataBits.Items.Add("7");
            cbDataBits.Items.Add("8");
            cbDataBits.SelectedIndex = 3;//默认8位数据

            cbStopBits.Items.Add("1");
            cbStopBits.Items.Add("1.5");
            cbStopBits.Items.Add("2");
            cbStopBits.SelectedIndex = 0;//默认8位数据

            cbVerify.Items.Add("None");
            cbVerify.Items.Add("Odd");
            cbVerify.Items.Add("Even");
            cbVerify.Items.Add("Mark");
            cbVerify.Items.Add("Space");
            cbVerify.SelectedIndex = 2;//默认偶校验

            cbFrameLength.Items.Add("256");
            cbFrameLength.Items.Add("512");
            cbFrameLength.Items.Add("1024");
            cbFrameLength.Items.Add("2048");
            cbFrameLength.Items.Add("4096");
            cbFrameLength.Items.Add("8192");
            cbFrameLength.Items.Add("16384");
            cbFrameLength.Items.Add("32768");
            cbFrameLength.Items.Add("65536");
            cbFrameLength.SelectedIndex = 0;//默认2KB
            frameLength = Convert.ToInt16(cbFrameLength.Text);//得到每帧程序内容长度

            try
            {
                StreamReader IniReader = new StreamReader("./PCB_INFO.INI", Encoding.Default);//加载配置文件
                IniReaderBUF = IniReader.ReadToEnd();//读取program文件
                IniReader.Close();//关闭文件
                IniReader.Dispose();//释放缓存

                string pattern = @"(?i)(?<=\[)(.*)(?=\])";
                MatchCollection matchCollection = Regex.Matches(IniReaderBUF, pattern);//PCB型号添加到选择框
                if (matchCollection.Count > 0)
                {
                    foreach (var match in matchCollection)
                    {
                        cbInformation.Items.Add(match.ToString());
                    }
                }
                cbInformation.SelectedIndex = 0;
            }
            catch
            {
                ProgramFileBUF1 = null;
                MessageBox.Show("无法读取配置文件", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            uiProgressIndicator1.Visible = false;//关闭等待提示
            RebootTime = 0;
            timer2.Stop();   //停止手动定时器

            Control.CheckForIllegalCrossThreadCalls = false;
            sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived); //订阅委托 


            this.tabPage3.Parent = null; //隐藏调试标签

        }

        private void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)//串口数据获取
        {
            byte[] bufData = new byte[sp1.BytesToRead];//串口接收数据临时缓存
            if (sp1.BytesToRead != 0)
            {
                try
                {
                    sp1.Read(bufData, 0, sp1.BytesToRead);

                    lock (locker)//加锁防止出错
                    {
                        SerialBuffer.AddRange(bufData);
                    }

                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error");
                    return;
                }
            }
            bufData = null;//释放内存
        }

        private void logTestPrintf(string logStr, System.Drawing.Color textColor)
        {
            DateTime rtcTime = DateTime.Now;

            uiRichTextBox2.SelectionColor = textColor;

            uiRichTextBox2.AppendText("[" + rtcTime.Year.ToString() + "-" + rtcTime.Month.ToString() + "-" + rtcTime.Day.ToString() + " "
                                    + rtcTime.Hour.ToString() + ":" + rtcTime.Minute.ToString() + ":" + rtcTime.Second.ToString() + "]>>"
                                    + logStr + "\r\n");

            uiRichTextBox2.SelectionStart = uiRichTextBox2.TextLength;
            uiRichTextBox2.Focus();
            rtcTime.Year.ToString();
            
        }
        private void uiButton9_Click(object sender, EventArgs e)
        {
            if (!sp1.IsOpen)//串口关闭状态
            {
                try
                {
                    string serialName = cbSerial.SelectedItem.ToString();//设置串口号 
                    sp1.PortName = serialName;
                    sp1.BaudRate = Convert.ToInt32(cbBaudRate.Text); //波特率 
                    sp1.DataBits = Convert.ToInt32(cbDataBits.Text); //数据位 

                    if (cbStopBits.Text == "1")
                    {
                        sp1.StopBits = StopBits.One;//停止位
                    }
                    else if (cbStopBits.Text == "1.5")
                    {
                        sp1.StopBits = StopBits.OnePointFive;//停止位
                    }
                    else if (cbStopBits.Text == "2")
                    {
                        sp1.StopBits = StopBits.Two;//停止位
                    }


                    if (cbVerify.Text == "None")
                    {
                        sp1.Parity = Parity.None;//无校验
                    }
                    else if (cbVerify.Text == "Odd")
                    {
                        sp1.Parity = Parity.Odd;
                    }
                    else if (cbVerify.Text == "Even")
                    {
                        sp1.Parity = Parity.Even;
                    }
                    else if (cbVerify.Text == "Mark")
                    {
                        sp1.Parity = Parity.Mark;
                    }
                    else if (cbVerify.Text == "Space")
                    {
                        sp1.Parity = Parity.Space;
                    }

                    sp1.WriteBufferSize = 4096;
                    sp1.ReadBufferSize = 4096;

                    sp1.Open(); //打开串口 

                    //状态栏设置 
                    if (sp1.IsOpen)
                    {
                        //设置必要控件不可用 
                        cbSerial.Enabled = false;
                        cbBaudRate.Enabled = false;
                        cbDataBits.Enabled = false;
                        cbStopBits.Enabled = false;
                        cbVerify.Enabled = false;
                        uiButton9.Text = "关闭串口";//按钮文字
                        uiTextBox28.Text = "已打开";
                        logTestPrintf("串口已打开......", System.Drawing.Color.Black);

                    }
                    else
                    {
                        //设置必要控件不可用 
                        cbSerial.Enabled = true;
                        cbBaudRate.Enabled = true;
                        cbDataBits.Enabled = true;
                        cbStopBits.Enabled = true;
                        cbVerify.Enabled = true;
                        uiButton9.Text = "打开串口";//按钮文字
                        uiTextBox28.Text = "已关闭";
                        logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                    }

                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error");
                    return;
                }
            }
            else
            {

                sp1.Close(); //关闭串口 
                //状态栏设置 
                if (sp1.IsOpen)
                {
                    //设置必要控件不可用 
                    cbSerial.Enabled = false;
                    cbBaudRate.Enabled = false;
                    cbDataBits.Enabled = false;
                    cbStopBits.Enabled = false;
                    cbVerify.Enabled = false;
                    uiButton9.Text = "关闭串口";//按钮文字
                    uiTextBox28.Text = "已打开";
                    logTestPrintf("串口已打开......", System.Drawing.Color.Black);

                }
                else
                {
                    //设置必要控件不可用 
                    cbSerial.Enabled = true;
                    cbBaudRate.Enabled = true;
                    cbDataBits.Enabled = true;
                    cbStopBits.Enabled = true;
                    cbVerify.Enabled = true;
                    uiButton9.Text = "打开串口";//按钮文字
                    uiTextBox28.Text = "已关闭";
                    logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                }

                logTestPrintf("串口关闭停止升级......", System.Drawing.Color.Black);
                updateTime = 0;
                updateStep = 0;//发送文件信息
                uiProcessBar1.Value = 0;//设置进度条
                timer1.Stop();   //停止询问命令定时器
                Array.Clear(array, 0, array.Length);//清空数组
                SerialBuffer.Clear();//清空串口缓冲区
            }
        }



        private void uiButton6_Click(object sender, EventArgs e)//打开升级文件
        {
            string verString;
            OpenFileDialog fileDialog1 = new OpenFileDialog();
            fileDialog1.Filter = "文本文件|*.bin";
            fileDialog1.RestoreDirectory = false;    //若为false，则打开对话框后为上次的目录。若为true，则为初始目录
            if (fileDialog1.ShowDialog() == DialogResult.OK)
                tbFilePath.Text = System.IO.Path.GetFullPath(fileDialog1.FileName);//将选中的文件的路径传递给TextBox “FilePath”

            //读取程序到缓存
            try
            {
                //将程序文件读入缓存
                ProgramBinBUF = System.IO.File.ReadAllBytes(tbFilePath.Text);//读取程序文件

                verString = "0x" + ProgramBinBUF[2049].ToString("X2") + ProgramBinBUF[2048].ToString("X2");

                if (uiTextBox24.Text != verString)//校验选择程序的设备类型编号
                {
                    uiTextBox23.Text = "V1.00";
                    logTestPrintf("注意！固件设备类型编号校验失败！请检查固件文件是否与硬件匹配！", System.Drawing.Color.Red);

                }
                else
                { 
                    uiTextBox23.Text = "V" + (ProgramBinBUF[2051] + ProgramBinBUF[2050]/100).ToString() + "." + (ProgramBinBUF[2050]%100).ToString();//获取并显示程序版本号
                    logTestPrintf("固件设备类型编号校验通过！"+" 固件版本:" + uiTextBox23.Text, System.Drawing.Color.Green);
                }

                uiTextBox21.Text = ProgramBinBUF.Length.ToString();//长度
                logTestPrintf("打开文件......", System.Drawing.Color.Black);
                updateTime = 0;//清空程序升级计时
                updateStep = 0;//清空程序升级步骤

                if (ProgramBinBUF.Length % frameLength == 0)//计算程序发送文件次数
                {
                    PrgSendNum = ProgramBinBUF.Length / frameLength;
                }
                else
                {
                    PrgSendNum = ProgramBinBUF.Length / frameLength;
                    PrgSendNum = PrgSendNum + 1;
                }
                PrgSendNum -= 1;//注意帧累加从0开始，此处应减1

            }
            catch
            {
                ProgramBinBUF = null;
                MessageBox.Show("无法读取ProgramBin！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        public static int CRC16(byte[] bytes, int len)
        {
            int crc = 0xffff;
            for (int i = 0; i < len; i++)
            {
                crc = crc ^ bytes[i];
                for (int j = 0; j < 8; j++)
                {
                    int temp;
                    temp = crc & 1;
                    crc = crc >> 1;
                    crc = crc & 0x7fff;
                    if (temp == 1)
                    {
                        crc = crc ^ 0xa001;
                    }
                    crc = crc & 0xffff;
                }
            }
            return crc;
        }


        //0a 05 10 60 ff 00 89 9f
        private void timer1_Tick(object sender, EventArgs e)//升级步骤定时器
        {
            updateTime++;//程序升级步骤计时

            //Int16 DeAdd = Convert.ToInt16(uiTextBox22.Text, 16);//val16_Str为16进制字符串
            //Int16 DeTnum = Convert.ToInt16(uiTextBox24.Text, 16);//val16_Str为16进制字符串

            Int16 DeAdd = Convert.ToInt16(uiTextBox22.Text.Substring(2), 16);//设备地址
            Int16 DeTnum = Convert.ToInt16(uiTextBox20.Text.Substring(2), 16);//设备重启地址
            Int16 DeType = Convert.ToInt16(uiTextBox24.Text.Substring(2), 16);//设备类型编号
            Int16 DeVersion = Convert.ToInt16((ProgramBinBUF[2051] << 8) + ProgramBinBUF[2050]);//程序版本
            Int32 DeLength = Convert.ToInt32(uiTextBox21.Text);//程序长度

            switch (updateStep)
            {
                case 0://发送重启命令
                {
                    try
                    {
                        int crcBuf = 0xFFFF;
                        byte[] statusInquireBuf = new byte[8];//状态查询命令
                        statusInquireBuf[0] = (byte)(DeAdd);
                        statusInquireBuf[1] = (byte)0x05;
                        statusInquireBuf[2] = (byte)(DeTnum >> 8);
                        statusInquireBuf[3] = (byte)(DeTnum);
                        statusInquireBuf[4] = (byte)0xFF;
                        statusInquireBuf[5] = (byte)0x00;
                        statusInquireBuf[6] = (byte)0x00;
                        statusInquireBuf[7] = (byte)0x00;

                        crcBuf = CRC16(statusInquireBuf, 6);
                        statusInquireBuf[6] = (byte)crcBuf; statusInquireBuf[7] = (byte)(crcBuf >> 8);
                        if (sp1.IsOpen)
                        {
                            sp1.Write(statusInquireBuf, 0, 8);//写数据,读所有状态命令
                            logTestPrintf("发送重启命令......", System.Drawing.Color.Black);
                        }
                        else
                        {
                            uiButton9.Text = "打开串口";//按钮文字
                            uiTextBox28.Text = "已关闭";
                            logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                            sp1.Close(); //关闭串口 
                        }
                        statusInquireBuf = null;//释放内存
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        updateTime = 0;
                        updateStep = 1;//发送文件信息
                    }
                    catch (System.Exception ex)
                    {
                        updateTime = 0;
                        updateStep = 0;//发送文件信息
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        MessageBox.Show(ex.Message, "重启命令发送错误");
                    }

                    break;
                }
                case 1://等待主板重启
                {

                    lock (locker)//加锁防止出错
                    {
                        array = SerialBuffer.ToArray();
                    }

                    if (updateTime <= ComInterval)//等待5秒
                    {
                        if (array.Length >= 8)//接收长度错误
                        {
                            if (((array[0] == DeAdd) && (array[2] == (byte)(DeTnum >> 8)) && (array[3] == (byte)DeTnum)))
                            {
                                logTestPrintf("主板重启成功......", System.Drawing.Color.Black);
                                updateStep = 2;//发送文件信息  
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                            else
                            {
                                logTestPrintf("主板重启失败......", System.Drawing.Color.Red);
                                updateStep = 0;//
                                timer1.Stop();   //停止询问命令定时器
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                        }
                    } else
                    {
                        logTestPrintf("主板重启失败......", System.Drawing.Color.Red);
                        updateStep = 0;//
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                    }
                    break;
                }
                case 2://发送升级程序命令
                {
                    try
                    {
                        timer2.Stop();   //停止手动定时器
                        int crcBuf = 0xFFFF;
                        byte[] statusInquireBuf = new byte[12];//状态查询命令
                        byte[] statusInquireCheck = new byte[6];//校验缓存

                        statusInquireBuf[0] = (byte)0xFA;
                        statusInquireBuf[1] = (byte)0xFB;
                        statusInquireBuf[2] = (byte)(DeAdd);
                        statusInquireBuf[3] = (byte)0x01;
                        statusInquireBuf[4] = (byte)0x00;
                        statusInquireBuf[5] = (byte)0x02;
                        statusInquireBuf[6] = (byte)(DeType >> 8);
                        statusInquireBuf[7] = (byte)(DeType);
                        statusInquireBuf[8] = (byte)0x00;
                        statusInquireBuf[9] = (byte)0x00;
                        statusInquireBuf[10] = (byte)0xFC;
                        statusInquireBuf[11] = (byte)0xFD;

                        for (int i = 0; i < statusInquireCheck.Length; i++)
                        {
                            statusInquireCheck[i] = statusInquireBuf[i + 2];
                        }

                        crcBuf = CRC16(statusInquireCheck, statusInquireCheck.Length);
                        statusInquireBuf[8] = (byte)crcBuf; statusInquireBuf[9] = (byte)(crcBuf >> 8);
                        if (sp1.IsOpen)
                        {
                            sp1.Write(statusInquireBuf, 0, 12);//写数据,读所有状态命令
                            logTestPrintf("发送升级程序命令......", System.Drawing.Color.Black);
                        }
                        else
                        {
                            uiButton9.Text = "打开串口";//按钮文字
                            uiTextBox28.Text = "已关闭";
                            logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                            sp1.Close(); //关闭串口 
                        }
                        statusInquireBuf = null;//释放内存
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        updateTime = 0;
                        updateStep = 3;//发送文件信息
                    }
                    catch (System.Exception ex)
                    {
                        updateTime = 0;
                        updateStep = 0;//发送文件信息
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        MessageBox.Show(ex.Message, "升级程序命令发送错误");
                    }

                    break;
                }
                case 3://等待主板回复
                {
   
                    lock (locker)//加锁防止出错
                    {
                        array = SerialBuffer.ToArray();
                    }

                    if (updateTime <= ComInterval)//等待5秒
                    {
                        if (array.Length >= 8)//接收长度错误
                        {
                            if (((array[6] == (byte)(DeType >> 8)) && (array[7] == (byte)DeType)))
                            {
                                logTestPrintf("升级程序返回......", System.Drawing.Color.Black);
                                updateStep = 4;//发送文件信息  
                                Array.Clear(array, 0, array.Length);//清空数组
                                uiProgressIndicator1.Visible = false;//关闭等待提示
                            }
                            else
                            {
                                logTestPrintf("设备类型编号错误......", System.Drawing.Color.Red);
                                updateStep = 0;//
                                timer1.Stop();   //停止询问命令定时器
                                timer2.Start();  //打开手动定时器
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                        }
                    }
                    else
                    {
                        logTestPrintf("设备升级程序命令未返回......", System.Drawing.Color.Red);
                        updateStep = 0;//
                        timer1.Stop();   //停止询问命令定时器
                        timer2.Start();  //打开手动定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                    }

                    break;
                }

                case 4://发送文件信息
                {
                    try
                    {
                        int crcBuf = 0xFFFF;
                        byte[] statusInquireBuf = new byte[18];//状态查询命令
                        byte[] statusInquireCheck = new byte[12];//校验缓存

                        statusInquireBuf[0] = (byte)0xFA;
                        statusInquireBuf[1] = (byte)0xFB;
                        statusInquireBuf[2] = (byte)(DeAdd);
                        statusInquireBuf[3] = (byte)0x03;
                        statusInquireBuf[4] = (byte)0x00;
                        statusInquireBuf[5] = (byte)0x08;
                        statusInquireBuf[6] = (byte)(DeType >> 8);
                        statusInquireBuf[7] = (byte)(DeType);
                        statusInquireBuf[8] = (byte)(DeVersion >> 8);
                        statusInquireBuf[9] = (byte)(DeVersion);
                        statusInquireBuf[10] = (byte)(DeLength >> 24);
                        statusInquireBuf[11] = (byte)(DeLength >> 16);
                        statusInquireBuf[12] = (byte)(DeLength >> 8);
                        statusInquireBuf[13] = (byte)(DeLength);
                        statusInquireBuf[14] = (byte)0x00;
                        statusInquireBuf[15] = (byte)0x00;
                        statusInquireBuf[16] = (byte)0xFC;
                        statusInquireBuf[17] = (byte)0xFD;

                        for (int i = 0; i < statusInquireCheck.Length; i++)
                        {
                            statusInquireCheck[i] = statusInquireBuf[i + 2];
                        }

                        crcBuf = CRC16(statusInquireCheck, statusInquireCheck.Length);
                        statusInquireBuf[14] = (byte)crcBuf; statusInquireBuf[15] = (byte)(crcBuf >> 8);
                        if (sp1.IsOpen)
                        {
                            sp1.Write(statusInquireBuf, 0, 18);//写数据,读所有状态命令
                            logTestPrintf("发送文件信息......", System.Drawing.Color.Black);
                        }
                        else
                        {
                            uiButton9.Text = "打开串口";//按钮文字
                            uiTextBox28.Text = "已关闭";
                            logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                            sp1.Close(); //关闭串口 
                        }
                        statusInquireBuf = null;//释放内存
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        updateTime = 0;
                        updateStep = 5;//发送文件信息
                    }
                    catch (System.Exception ex)
                    {
                        updateTime = 0;
                        updateStep = 0;//发送文件信息
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        MessageBox.Show(ex.Message, "文件信息发送错误");
                    }

                    break;
                }
                case 5://等待主板回复
                {

                    lock (locker)//加锁防止出错
                    {
                        array = SerialBuffer.ToArray();
                    }

                    if (updateTime <= ComInterval)//等待5秒
                    {
                        if (array.Length >= 8)//接收长度错误
                        {
                            if (((array[6] == (byte)(DeType >> 8)) && (array[7] == (byte)DeType)))
                            {
                                logTestPrintf("文件信息返回......", System.Drawing.Color.Black);
                                updateStep = 6;//发送文件信息  
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                            else
                            {
                                logTestPrintf("设备类型编号错误......", System.Drawing.Color.Red);
                                updateStep = 0;//
                                timer1.Stop();   //停止询问命令定时器
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                        }
                    }
                    else
                    {
                        logTestPrintf("文件信息命令未返回......", System.Drawing.Color.Red);
                        updateStep = 0;//
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                    }

                    break;
                }

                case 6://发送程序文件
                {
                    try
                    {
                        int crcBuf = 0xFFFF;
                        int numBuf = 0;
                        //byte[] statusInquireBuf = new byte[266];//状态查询命令
                        //byte[] statusInquireCheck = new byte[260];//校验缓存

                        byte[] statusInquireBuf = new byte[frameLength + 10];//状态查询命令
                        byte[] statusInquireCheck = new byte[frameLength + 4];//校验缓存

                        statusInquireBuf[0] = (byte)0xFA;
                        statusInquireBuf[1] = (byte)0xFB;
                        statusInquireBuf[2] = (byte)(DeAdd);
                        statusInquireBuf[3] = (byte)0x05;
                        statusInquireBuf[4] = (byte)(frameLength >> 8);
                        statusInquireBuf[5] = (byte)(frameLength);

                        if (DeLength % frameLength == 0)
                        {

                            for (numBuf = 0; numBuf < frameLength; numBuf++)
                            {
                                statusInquireBuf[6 + numBuf] = ProgramBinBUF[numBuf + (PrgSendSum * frameLength)];
                            }
                            uiTextBox18.Text = (PrgSendSum * frameLength).ToString();//计算已下载长度
                        }
                        else
                        {
                            if (PrgSendSum < PrgSendNum)
                            {

                                for (numBuf = 0; numBuf < frameLength; numBuf++)
                                {
                                    statusInquireBuf[6 + numBuf] = ProgramBinBUF[numBuf + (PrgSendSum * frameLength)];
                                }
                                uiTextBox18.Text = (PrgSendSum * frameLength).ToString();//计算已下载长度
                            }
                            else
                            {
                                int endDataLength = DeLength - PrgSendSum * frameLength;

                                statusInquireBuf[4] = (byte)(endDataLength >> 8);
                                statusInquireBuf[5] = (byte)(endDataLength);

                                for (numBuf = 0; numBuf < (DeLength - PrgSendSum * frameLength); numBuf++)//发送结束帧
                                {
                                    statusInquireBuf[6 + numBuf] = ProgramBinBUF[numBuf + (PrgSendSum * frameLength)];
                                }
                                uiTextBox18.Text = ((PrgSendSum * frameLength) + endDataLength).ToString();//计算已下载长度
                            }
                        }

                        statusInquireBuf[numBuf + 6 + 0] = (byte)0x00;
                        statusInquireBuf[numBuf + 6 + 1] = (byte)0x00;
                        statusInquireBuf[numBuf + 6 + 2] = (byte)0xFC;
                        statusInquireBuf[numBuf + 6 + 3] = (byte)0xFD;

                        if (PrgSendSum < PrgSendNum)
                        {
                            for (int i = 0; i < statusInquireCheck.Length; i++)
                            {
                                statusInquireCheck[i] = statusInquireBuf[i + 2];
                            }
                            crcBuf = CRC16(statusInquireCheck, statusInquireCheck.Length);
                        }
                        else
                        {
                            for (int i = 0; i < (DeLength - PrgSendSum * frameLength + 4); i++)
                            {
                                statusInquireCheck[i] = statusInquireBuf[i + 2];
                            }
                            crcBuf = CRC16(statusInquireCheck, (DeLength - PrgSendSum * frameLength + 4));
                        }

                        statusInquireBuf[numBuf + 6 + 0] = (byte)crcBuf; statusInquireBuf[numBuf + 6 + 1] = (byte)(crcBuf >> 8);
                        if (sp1.IsOpen)
                        {
                            sp1.Write(statusInquireBuf, 0, (numBuf + 10));//写数据,读所有状态命令
                            if (ProgramBinBUF.Length % frameLength == 0)//计算程序发送文件次数
                            {
                                logTestPrintf("发送程序帧:" + PrgSendNum.ToString() + "/" + (PrgSendSum + 1).ToString(), System.Drawing.Color.Black);
                            }
                            else
                            {
                                logTestPrintf("发送程序帧:" + (PrgSendNum + 1).ToString() + "/" + (PrgSendSum + 1).ToString(), System.Drawing.Color.Black);
                            }
                            
                        }
                        else
                        {
                            uiButton9.Text = "打开串口";//按钮文字
                            uiTextBox28.Text = "已关闭";
                            logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                            sp1.Close(); //关闭串口 
                        }
                        statusInquireBuf = null;//释放内存
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        updateTime = 0;
                        updateStep = 7;//发送文件信息
                        PrgSendSum++;//帧数计数
                    }
                    catch (System.Exception ex)
                    {
                        updateTime = 0;
                        updateStep = 0;//发送文件信息
                        PrgSendSum = 0;
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        MessageBox.Show(ex.Message, "文件信息发送错误");
                    }

                    break;
                }
                case 7://等待主板回复
                {

                    lock (locker)//加锁防止出错
                    {
                        array = SerialBuffer.ToArray();
                    }

                    if (updateTime <= ComInterval)//等待5秒
                    {
                        if (array.Length >= 8)//接收长度错误
                        {
                            if (array[3] == 0x06)
                            {
                                logTestPrintf("程序文件返回......", System.Drawing.Color.Black);
                                Array.Clear(array, 0, array.Length);//清空数组

                                if (PrgSendSum > PrgSendNum)//文件发送完成
                                {
                                    updateStep = 8;//发送结束帧
                                }
                                else
                                {
                                    updateStep = 6;//未发送完成
                                    uiProcessBar1.Value = (Int16)(((float)((float)PrgSendSum / (float)PrgSendNum)) * 100);//设置进度条
                                }

                            }
                            else
                            {
                                logTestPrintf("程序文件返回错误......", System.Drawing.Color.Red);
                                updateStep = 0;//
                                timer1.Stop();   //停止询问命令定时器
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                        }
                    }
                    else
                    {
                        logTestPrintf("文件命令未返回......", System.Drawing.Color.Red);
                        updateTime = 0;
                        updateStep = 0;//发送文件信息
                        PrgSendSum = 0;
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                    }
                    break;
                }

                case 8://发送升级程序命令
                {
                    try
                    {
                        int crcBuf = 0xFFFF;
                        byte[] statusInquireBuf = new byte[12];//状态查询命令
                        byte[] statusInquireCheck = new byte[6];//校验缓存

                        statusInquireBuf[0] = (byte)0xFA;
                        statusInquireBuf[1] = (byte)0xFB;
                        statusInquireBuf[2] = (byte)(DeAdd);
                        statusInquireBuf[3] = (byte)0x07;
                        statusInquireBuf[4] = (byte)0x00;
                        statusInquireBuf[5] = (byte)0x02;
                        statusInquireBuf[6] = (byte)(DeType >> 8);
                        statusInquireBuf[7] = (byte)(DeType);
                        statusInquireBuf[8] = (byte)0x00;
                        statusInquireBuf[9] = (byte)0x00;
                        statusInquireBuf[10] = (byte)0xFC;
                        statusInquireBuf[11] = (byte)0xFD;

                        for (int i = 0; i < statusInquireCheck.Length; i++)
                        {
                            statusInquireCheck[i] = statusInquireBuf[i + 2];
                        }

                        crcBuf = CRC16(statusInquireCheck, statusInquireCheck.Length);
                        statusInquireBuf[8] = (byte)crcBuf; statusInquireBuf[9] = (byte)(crcBuf >> 8);
                        if (sp1.IsOpen)
                        {
                            sp1.Write(statusInquireBuf, 0, 12);//写数据,读所有状态命令
                            logTestPrintf("发送结束帧......", System.Drawing.Color.Black);
                        }
                        else
                        {
                            uiButton9.Text = "打开串口";//按钮文字
                            uiTextBox28.Text = "已关闭";
                            logTestPrintf("串口已关闭......", System.Drawing.Color.Black);
                            sp1.Close(); //关闭串口 
                        }
                        statusInquireBuf = null;//释放内存
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        updateTime = 0;
                        updateStep = 9;//发送文件信息
                    }
                    catch (System.Exception ex)
                    {
                        updateTime = 0;
                        updateStep = 0;//发送文件信息
                        PrgSendSum = 0;
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                        SerialBuffer.Clear();//清空串口缓冲区
                        MessageBox.Show(ex.Message, "结束帧发送错误");
                    }

                    break;
                }

                case 9://等待主板回复
                {

                    lock (locker)//加锁防止出错
                    {
                        array = SerialBuffer.ToArray();
                    }

                    if (updateTime <= (ComInterval*10))//等待5秒
                    {
                        if (array.Length >= 8)//接收长度错误
                        {
                            if (((array[6] == (byte)(DeType >> 8)) && (array[7] == (byte)DeType)))
                            {
                                logTestPrintf("程序升级完成......", System.Drawing.Color.Green);
                                uiProcessBar1.Value = 100;//设置进度条
                                updateStep = 0;//
                                timer1.Stop();   //停止询问命令定时器
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                            else
                            {
                                logTestPrintf("设备类型编号错误......", System.Drawing.Color.Red);
                                updateStep = 0;//
                                timer1.Stop();   //停止询问命令定时器
                                Array.Clear(array, 0, array.Length);//清空数组
                            }
                        }
                    }
                    else
                    {
                        logTestPrintf("结束帧未返回......", System.Drawing.Color.Red);
                        updateStep = 0;//
                        timer1.Stop();   //停止询问命令定时器
                        Array.Clear(array, 0, array.Length);//清空数组
                    }
                    break;
                }
                default: break;

            }
        }

        private void uiButton7_Click(object sender, EventArgs e)
        {

            if (tbFilePath.Text != "")
            {
                logTestPrintf("开始自动下载......", System.Drawing.Color.Black);
                updateTime = 0;
                updateStep = 0;//
                PrgSendSum = 0;
                uiProcessBar1.Value = 0;//设置进度条
                ComInterval = (Convert.ToInt32(uiTextBox25.Text)) / 100; //计算命令等待间隔
                Array.Clear(array, 0, array.Length);//清空数组
                SerialBuffer.Clear();//清空串口缓冲区
                timer1.Start();   //停止询问命令定时器
            }
            else
            {
                logTestPrintf("未找到文件或文件路径为空！", System.Drawing.Color.Red);
                updateStep = 0;//
                timer1.Stop();   //停止询问命令定时器
            }
        }

        private void uiButton12_Click(object sender, EventArgs e)//解析配置文件
        {
            string verString;
            string BinFileUrl = "";

            try
            {
                

                var PCB_INFO_INI = new IniFile("./PCB_INFO.INI");//打开配置文件

                logTestPrintf("加载配置信息......", System.Drawing.Color.Black);
                cbBaudRate.Text = PCB_INFO_INI.Read(cbInformation.Text, "BaudRate", "57600").ToString();//获取波特率
                logTestPrintf("BaudRate:"+ cbBaudRate.Text, System.Drawing.Color.Black);
                cbDataBits.Text = PCB_INFO_INI.Read(cbInformation.Text, "DataBits", "8").ToString();//数据位
                logTestPrintf("DataBits:" + cbDataBits.Text, System.Drawing.Color.Black);
                cbStopBits.Text = PCB_INFO_INI.Read(cbInformation.Text, "StopBits", "1").ToString();//停止位
                logTestPrintf("StopBits:" + cbStopBits.Text, System.Drawing.Color.Black);
                cbVerify.Text = PCB_INFO_INI.Read(cbInformation.Text, "Parity", "Even").ToString();//校验
                logTestPrintf("Parity:" + cbVerify.Text, System.Drawing.Color.Black);

                uiTextBox24.Text = PCB_INFO_INI.Read(cbInformation.Text, "DeviceType", "0x1105").ToString();//设备类型
                logTestPrintf("DeviceType:" + uiTextBox24.Text, System.Drawing.Color.Black);
                uiTextBox22.Text = PCB_INFO_INI.Read(cbInformation.Text, "DeviceAddress", "0x0A").ToString();//设备地址
                logTestPrintf("DeviceAddress:" + uiTextBox22.Text, System.Drawing.Color.Black);
                uiTextBox20.Text = PCB_INFO_INI.Read(cbInformation.Text, "RestartAddress", "0x1060").ToString();//重启地址
                logTestPrintf("RestartAddress:" + uiTextBox20.Text, System.Drawing.Color.Black);
                uiTextBox25.Text = PCB_INFO_INI.Read(cbInformation.Text, "InterframeGap", "600").ToString();//间隔时间
                logTestPrintf("InterframeGap:" + uiTextBox25.Text, System.Drawing.Color.Black);
                cbFrameLength.Text = PCB_INFO_INI.Read(cbInformation.Text, "FrameLength", "2").ToString();//帧长度
                logTestPrintf("FrameLength:" + cbFrameLength.Text, System.Drawing.Color.Black);
                frameLength = Convert.ToInt16(cbFrameLength.Text);//得到每帧程序内容长度

                BinFileUrl = PCB_INFO_INI.Read(cbInformation.Text, "GitLink", "None").ToString();

            }
            catch
            {
                ProgramFileBUF1 = null;
                MessageBox.Show("无法读取配置文件", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (BinFileUrl == "None")
            {
                logTestPrintf("GitLink:" + BinFileUrl, System.Drawing.Color.Red);
            }
            else
            {
                logTestPrintf("GitLink:" + BinFileUrl, System.Drawing.Color.Green);

                try
                {
                    using (WebClient client = new WebClient())
                    {
                        client.DownloadFile(BinFileUrl, @"./program.bin");
                        logTestPrintf("拉取可执行文件......", System.Drawing.Color.Black);
                        tbFilePath.Text = "./program.bin";
                    }


                    //将程序文件读入缓存
                    ProgramBinBUF = System.IO.File.ReadAllBytes(tbFilePath.Text);//读取程序文件

                    verString = "0x" + ProgramBinBUF[2049].ToString("X2") + ProgramBinBUF[2048].ToString("X2");

                    if (uiTextBox24.Text != verString)//校验选择程序的设备类型编号
                    {
                        uiTextBox23.Text = "V1.00";
                        logTestPrintf("注意！固件设备类型编号校验失败！请检查固件文件是否与硬件匹配！", System.Drawing.Color.Red);

                    }
                    else
                    {
                        //uiTextBox23.Text = "V" + (ProgramBinBUF[2051] + ProgramBinBUF[2050] / 100).ToString() + "." + (ProgramBinBUF[2050] % 100).ToString();//获取并显示程序版本号
                        uiTextBox23.Text = "V" + (((ProgramBinBUF[2051]<<8) + ProgramBinBUF[2050])/100).ToString() + "." + (((ProgramBinBUF[2051] << 8) + ProgramBinBUF[2050]) % 100).ToString();
                        logTestPrintf("固件设备类型编号校验通过！" + " 固件版本:" + uiTextBox23.Text, System.Drawing.Color.Green);
                    }

                    uiTextBox21.Text = ProgramBinBUF.Length.ToString();//长度
                    logTestPrintf("打开文件......", System.Drawing.Color.Black);
                    updateTime = 0;//清空程序升级计时
                    updateStep = 0;//清空程序升级步骤

                    if (ProgramBinBUF.Length % frameLength == 0)//计算程序发送文件次数
                    {
                        PrgSendNum = ProgramBinBUF.Length / frameLength;
                    }
                    else
                    {
                        PrgSendNum = ProgramBinBUF.Length / frameLength;
                        PrgSendNum = PrgSendNum + 1;
                    }
                    PrgSendNum -= 1;//注意帧累加从0开始，此处应减1
                }
                catch
                {
                    logTestPrintf("文件拉取失败,请手动选择可执行文件......", System.Drawing.Color.Red);
                }
            }
        }

        private void cbInformation_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                string PCB_INFO_INI = Application.StartupPath + @"./PCB_INFO.INI";//配置文档中的地址
                byte[] PCB_INFO_BUF = new byte[102400];//注意！配置文件最大100KB
                int bufLen = 0;
                bufLen = GetPrivateProfileString(cbInformation.Text, "DeviceName", "", PCB_INFO_BUF, 102400, PCB_INFO_INI);//读配置文档
                uiTextBox26.Text = Encoding.UTF8.GetString(PCB_INFO_BUF, 0, bufLen);
            }
            catch
            {
                MessageBox.Show("无法读取配置文件", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void uiButton10_Click(object sender, EventArgs e)
        {
            logTestPrintf("手动停止升级......", System.Drawing.Color.Black);
            updateTime = 0;
            updateStep = 0;//发送文件信息
            PrgSendSum = 0;
            uiProcessBar1.Value = 0;//设置进度条
            timer1.Stop();   //停止询问命令定时器
            uiProgressIndicator1.Visible = false;//关闭等待提示
            RebootTime = 0;
            timer2.Stop();   //停止手动定时器
            Array.Clear(array, 0, array.Length);//清空数组
            SerialBuffer.Clear();//清空串口缓冲区
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            RebootTime++;

            if (RebootTime >= 10)
            {
                logTestPrintf("手动下载超时......", System.Drawing.Color.Red);
                updateTime = 0;
                updateStep = 0;//发送文件信息
                PrgSendSum = 0;
                uiProcessBar1.Value = 0;//设置进度条
                timer1.Stop();   //停止询问命令定时器
                uiProgressIndicator1.Visible = false;//关闭等待提示
                RebootTime = 0;
                timer2.Stop();   //停止手动定时器
                Array.Clear(array, 0, array.Length);//清空数组
                SerialBuffer.Clear();//清空串口缓冲区
            }
            else
            {
                if ((updateStep == 0) || (updateStep == 1))
                {
                    uiProgressIndicator1.Visible = true;//打开等待提示
                    updateTime = 0;
                    updateStep = 2;
                    PrgSendSum = 0;
                    uiProcessBar1.Value = 0;//设置进度条
                    ComInterval = (Convert.ToInt32(uiTextBox25.Text)) / 100; //计算命令等待间隔
                    Array.Clear(array, 0, array.Length);//清空数组
                    SerialBuffer.Clear();//清空串口缓冲区
                    timer1.Start();   //停止询问命令定时器
                }
                else
                {
                    timer2.Stop();   //停止手动定时器
                    uiProgressIndicator1.Visible = false;//关闭等待提示
                }

            }


        }

        private void uiButton11_Click(object sender, EventArgs e)//打开配置文件
        {
            string filePath = @"PCB_INFO.INI";
            Process.Start(filePath);
        }

        private void uiButton13_Click(object sender, EventArgs e)
        {
            this.tabPage3.Parent = null; //隐藏标签
            uiTextBox27.Text = null;
        }

        private void uiButton14_Click(object sender, EventArgs e)
        {
            if (uiTextBox27.Text == "songxing")//校验密码
            {
                this.tabPage3.Parent = this.uiTabControl1;//显示标签
            }
            else
            {
                MessageBox.Show("密码错误！", "Error");
            }
        }

        private void uiButton8_Click(object sender, EventArgs e)
        {
            uiProgressIndicator1.Visible = true;//打开等待提示
            RebootTime = 0;
            timer2.Start();   //停止手动定时器
            logTestPrintf("开始手动下载......", System.Drawing.Color.Black);

        }

        private void uiButton2_Click(object sender, EventArgs e)//app1
        {
            string buf_text1 = "";
            Int32 buf_date_text1 = 0;
            string buf_text2 = "";
            Int32 buf_date_text2 = 0;
            OpenFileDialog fileDialog2 = new OpenFileDialog();
            fileDialog2.Filter = "文本文件|*.hex";
            fileDialog2.RestoreDirectory = false;    //若为false，则打开对话框后为上次的目录。若为true，则为初始目录
            if (fileDialog2.ShowDialog() == DialogResult.OK)
                uiTextBox10.Text = System.IO.Path.GetFullPath(fileDialog2.FileName);//将选中的文件的路径传递给TextBox “FilePath”

            //读取program1到缓存
            try
            {
                //将program文件读入缓存
                StreamReader FileProgram1 = new StreamReader(uiTextBox10.Text, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                ProgramFileBUF1 = FileProgram1.ReadToEnd();//读取program文件
                FileProgram1.Close();//关闭文件
                FileProgram1.Dispose();//释放缓存

                uiTextBox9.Text = Path.GetFileName(uiTextBox10.Text);//文件名
                uiTextBox7.Text = ProgramFileBUF1.Length.ToString();//长度

                uiTextBox8.Text = "0x" + ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":02") + 9), 4)
                                + ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":10") + 3), 4);//首地址

                uiTextBox6.Text = "0x" + ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":00") - 12), 8);//入口地址


                if ((ProgramFileBUF1.LastIndexOf(":04") - ProgramFileBUF1.LastIndexOf(":10")) > 45)//判断是否有半行程序文件
                {
                    buf_text1 = ProgramFileBUF1.Substring((ProgramFileBUF1.LastIndexOf(":02") + 9), 4)
                                    + ProgramFileBUF1.Substring((ProgramFileBUF1.LastIndexOf(":10") + 48), 4);//取程序尾地址字符串
                    buf_text2 = ProgramFileBUF1.Substring((ProgramFileBUF1.LastIndexOf(":10") + 46), 2);//取程序最后一行长度字符串

                    buf_date_text1 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber)
                                    + Int32.Parse(buf_text2, System.Globalization.NumberStyles.HexNumber);//得到程序总长度

                    buf_text1 = ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":02") + 9), 4)
                                    + ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":10") + 3), 4);//首地址

                    buf_date_text2 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber);

                    buf_date_text2 = buf_date_text1 - buf_date_text2;

                    uiTextBox16.Text = "0x" + buf_date_text2.ToString("X");
                }else
                {

                    buf_text1 = ProgramFileBUF1.Substring((ProgramFileBUF1.LastIndexOf(":02") + 9), 4)
                                    + ProgramFileBUF1.Substring((ProgramFileBUF1.LastIndexOf(":10") + 3), 4);//取程序尾地址字符串
                    buf_text2 = ProgramFileBUF1.Substring((ProgramFileBUF1.LastIndexOf(":10") + 1), 2);//取程序最后一行长度字符串

                    buf_date_text1 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber)
                                    + Int32.Parse(buf_text2, System.Globalization.NumberStyles.HexNumber);//得到程序总长度

                    buf_text1 = ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":02") + 9), 4)
                                    + ProgramFileBUF1.Substring((ProgramFileBUF1.IndexOf(":10") + 3), 4);//首地址

                    buf_date_text2 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber);

                    buf_date_text2 = buf_date_text1 - buf_date_text2;

                    uiTextBox16.Text = "0x" + buf_date_text2.ToString("X");
                }

            }
            catch
            {
                ProgramFileBUF1 = null;
                MessageBox.Show("无法读取APP1！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void uiCheckBox1_ValueChanged(object sender, bool value)//固件1完整性标志
        {
            try
            {
                //将IPSW1文件读入缓存
                StreamReader FileIPSW1 = new StreamReader("./IPSW1_INFO.HEX", System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                IPSW1_BUF = FileIPSW1.ReadToEnd();//读取program文件
                FileIPSW1.Close();//关闭文件
                FileIPSW1.Dispose();//释放缓存
            }
            catch
            {
                IPSW1_BUF = null;
                MessageBox.Show("无法读取固件1信息文件！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void uiButton3_Click(object sender, EventArgs e)//app2
        {
            string buf_text1 = "";
            Int32 buf_date_text1 = 0;
            string buf_text2 = "";
            Int32 buf_date_text2 = 0;
            OpenFileDialog fileDialog2 = new OpenFileDialog();
            fileDialog2.Filter = "文本文件|*.hex";
            fileDialog2.RestoreDirectory = false;    //若为false，则打开对话框后为上次的目录。若为true，则为初始目录
            if (fileDialog2.ShowDialog() == DialogResult.OK)
                uiTextBox15.Text = System.IO.Path.GetFullPath(fileDialog2.FileName);//将选中的文件的路径传递给TextBox “FilePath”


            //读取program2到缓存中
            try
            {
                //将program文件读入缓存
                StreamReader FileProgram2 = new StreamReader(uiTextBox15.Text, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                ProgramFileBUF2 = FileProgram2.ReadToEnd();//读取program文件
                FileProgram2.Close();//关闭文件
                FileProgram2.Dispose();//释放缓存

                uiTextBox14.Text = Path.GetFileName(uiTextBox15.Text);//文件名
                uiTextBox12.Text = ProgramFileBUF2.Length.ToString();//长度

                uiTextBox13.Text = "0x" + ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":02") + 9), 4)
                                + ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":10") + 3), 4);//首地址

                uiTextBox11.Text = "0x" + ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":00") - 12), 8);//入口地址

                if ((ProgramFileBUF2.LastIndexOf(":04") - ProgramFileBUF2.LastIndexOf(":10")) > 45)//判断是否有半行程序文件
                {
                    buf_text1 = ProgramFileBUF2.Substring((ProgramFileBUF2.LastIndexOf(":02") + 9), 4)
                                + ProgramFileBUF2.Substring((ProgramFileBUF2.LastIndexOf(":10") + 48), 4);//取程序尾地址字符串
                    buf_text2 = ProgramFileBUF2.Substring((ProgramFileBUF2.LastIndexOf(":10") + 46), 2);//取程序最后一行长度字符串

                    buf_date_text1 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber)
                                    + Int32.Parse(buf_text2, System.Globalization.NumberStyles.HexNumber);//得到程序总长度

                    buf_text1 = ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":02") + 9), 4)
                                    + ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":10") + 3), 4);//首地址

                    buf_date_text2 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber);

                    buf_date_text2 = buf_date_text1 - buf_date_text2;

                    uiTextBox17.Text = "0x" + buf_date_text2.ToString("X");
                }
                else
                {

                    buf_text1 = ProgramFileBUF2.Substring((ProgramFileBUF2.LastIndexOf(":02") + 9), 4)
                                    + ProgramFileBUF2.Substring((ProgramFileBUF2.LastIndexOf(":10") + 3), 4);//取程序尾地址字符串
                    buf_text2 = ProgramFileBUF2.Substring((ProgramFileBUF2.LastIndexOf(":10") + 1), 2);//取程序最后一行长度字符串

                    buf_date_text1 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber)
                                    + Int32.Parse(buf_text2, System.Globalization.NumberStyles.HexNumber);//得到程序总长度

                    buf_text1 = ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":02") + 9), 4)
                                    + ProgramFileBUF2.Substring((ProgramFileBUF2.IndexOf(":10") + 3), 4);//首地址

                    buf_date_text2 = Int32.Parse(buf_text1, System.Globalization.NumberStyles.HexNumber);

                    buf_date_text2 = buf_date_text1 - buf_date_text2;

                    uiTextBox17.Text = "0x" + buf_date_text2.ToString("X");
                }

            }
            catch
            {
                ProgramFileBUF2 = null;
                MessageBox.Show("无法读取APP2！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void uiButton4_Click(object sender, EventArgs e)//合并按钮
        {
            string text_buf1 = "";
            string text_buf2 = "";
            string text_buf3 = "";
            Int16 sum_buf = 0;
            Int32 num_buf = 0;
            Int32 num_buf1 = 0;
            string string_num_buf = "";

            if ((uiTextBox1.Text != "") && (uiTextBox10.Text != ""))//判断两个输入文件的地址不为空
            {

                //合并第一个program到boot文件中
                //去掉boot文件中的文件结束帧

                BootloaderBUF_CP = BootloaderBUF.Substring(0, (BootloaderBUF.Length - 13));//去掉最后一行13个字符

                if (uiCheckBox1.Checked == true)//固件1完整性标志
                {

                    text_buf1 = uiTextBox16.Text.Remove(0, 2);//删除“0x”

                    switch (text_buf1.Length)
                    {

                        case 4:
                        {
                            text_buf2 = text_buf1.Remove(0, 2);//删除前两个长度
                            text_buf1 = text_buf1.Remove(2, 2);//删除后两个长度
                            text_buf2 = text_buf2 + text_buf1;//调换位置重新组合
                            IPSW1_BUF = IPSW1_BUF.Remove(71, 4);//删除原有长度
                            IPSW1_BUF = IPSW1_BUF.Insert(71, text_buf2);//插入文件长度
                            break;
                        }
                        case 5:
                        {
                            text_buf2 = text_buf1.Remove(1, 4);//删除后四个字符，得到第一个字符
                            text_buf3 = text_buf1.Remove(0, 3);//删除前三个字符，得到后两个字符
                            text_buf1 = text_buf1.Remove(0, 1);//删除第一个字符
                            text_buf1 = text_buf1.Remove(2, 2);//删除第后两个字符，得到中间两个字符
                            text_buf2 = text_buf3 + text_buf1 + "0" + text_buf2;
                            IPSW1_BUF = IPSW1_BUF.Remove(71, 6);//删除原有长度
                            IPSW1_BUF = IPSW1_BUF.Insert(71, text_buf2);//插入文件长度
                            break;
                        }
                        case 6:
                        {
                            text_buf2 = text_buf1.Remove(2, 4);//删除后四个字符，得到前两个字符
                            text_buf3 = text_buf1.Remove(0, 4);//删除前四个字符，得到后两个字符
                            text_buf1 = text_buf1.Remove(0, 2);//删除前两个字符
                            text_buf1 = text_buf1.Remove(2, 2);//删除第后两个字符，得到中间两个字符
                            text_buf2 = text_buf3 + text_buf1 + text_buf2;
                            IPSW1_BUF = IPSW1_BUF.Remove(71, 6);//删除原有长度
                            IPSW1_BUF = IPSW1_BUF.Insert(71, text_buf2);//插入文件长度
                            break;
                        }
                        default: break;
                    }

                    IPSW1_BUF = IPSW1_BUF.Remove(103, 2);//删除原有校验位
                    num_buf = 0;//清零累加值
                    for (sum_buf = 0; sum_buf < 20; sum_buf++)
                    {
                        num_buf += Int32.Parse(IPSW1_BUF.Substring(((sum_buf * 2) + 63), 2), System.Globalization.NumberStyles.HexNumber);//计算累加和
                    }

                    num_buf = 0x100 - num_buf;//计算校验位

                    string_num_buf = num_buf.ToString("X2");

                    string_num_buf = string_num_buf.Substring((string_num_buf.Length - 2), 2);

                    IPSW1_BUF = IPSW1_BUF.Insert(103, string_num_buf);//插入校验

                    StreamWriter streamWriter1 = new StreamWriter(uiTextBox1.Text);//创建写入流
                    streamWriter1.Write(BootloaderBUF_CP + IPSW1_BUF);//合并并写入到文件中
                    streamWriter1.Flush();//刷新缓存
                    streamWriter1.Close();//关闭流
                }

                try
                {
                    //将boot文件读入缓存
                    StreamReader FileBootloader = new StreamReader(uiTextBox1.Text, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                    BootloaderBUF = FileBootloader.ReadToEnd();//读取program文件
                    FileBootloader.Close();//关闭文件
                    FileBootloader.Dispose();//释放缓存
                }
                catch
                {
                    BootloaderBUF = null;
                    MessageBox.Show("文件合并失败！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (uiCheckBox2.Checked == true)//固件2完整性标志
                {
                    text_buf1 = uiTextBox17.Text.Remove(0, 2);//删除“0x”

                    switch (text_buf1.Length)
                    {
                        case 4:
                        {
                            text_buf2 = text_buf1.Remove(0, 2);//删除前两个长度
                            text_buf1 = text_buf1.Remove(2, 2);//删除后两个长度
                            text_buf2 = text_buf2 + text_buf1;//调换位置重新组合
                            IPSW2_BUF = IPSW2_BUF.Remove(54, 4);//删除原有长度
                            IPSW2_BUF = IPSW2_BUF.Insert(54, text_buf2);//插入文件长度
                            break;
                        }
                        case 5:
                        {
                            text_buf2 = text_buf1.Remove(1, 4);//删除后四个字符，得到第一个字符
                            text_buf3 = text_buf1.Remove(0, 3);//删除前三个字符，得到后两个字符
                            text_buf1 = text_buf1.Remove(0, 1);//删除第一个字符
                            text_buf1 = text_buf1.Remove(2, 2);//删除第后两个字符，得到中间两个字符
                            text_buf2 = text_buf3 + text_buf1 + "0" + text_buf2;
                            IPSW2_BUF = IPSW2_BUF.Remove(54, 6);//删除原有长度
                            IPSW2_BUF = IPSW2_BUF.Insert(54, text_buf2);//插入文件长度
                            break;
                        }
                        case 6:
                        {
                            text_buf2 = text_buf1.Remove(2, 4);//删除后四个字符，得到前两个字符
                            text_buf3 = text_buf1.Remove(0, 4);//删除前四个字符，得到后两个字符
                            text_buf1 = text_buf1.Remove(0, 2);//删除前两个字符
                            text_buf1 = text_buf1.Remove(2, 2);//删除第后两个字符，得到中间两个字符
                            text_buf2 = text_buf3 + text_buf1 + text_buf2;
                            IPSW2_BUF = IPSW2_BUF.Remove(54, 6);//删除原有长度
                            IPSW2_BUF = IPSW2_BUF.Insert(54, text_buf2);//插入文件长度
                            break;
                        }
                        default: break;
                    }

                    IPSW2_BUF = IPSW2_BUF.Remove(86, 2);//删除原有校验位

                    num_buf = 0;//清零累加值
                    for (sum_buf = 0; sum_buf < 20; sum_buf++)
                    {
                        num_buf1 = Int32.Parse(IPSW2_BUF.Substring(((sum_buf * 2) + 46), 2), System.Globalization.NumberStyles.HexNumber);//计算累加和
                        num_buf += num_buf1;
                    }

                    num_buf = 0x100 - num_buf;//计算校验位

                    string_num_buf = num_buf.ToString("X2");

                    string_num_buf = string_num_buf.Substring((string_num_buf.Length - 2), 2);

                    IPSW2_BUF = IPSW2_BUF.Insert(86, string_num_buf);//插入校验

                    StreamWriter streamWriter2 = new StreamWriter(uiTextBox1.Text);//创建写入流
                    streamWriter2.Write(BootloaderBUF + IPSW2_BUF);//合并并写入到文件中  
                    streamWriter2.Flush();//刷新缓存
                    streamWriter2.Close();//关闭流
                }

                try
                {
                    //将boot文件读入缓存
                    StreamReader FileBootloader = new StreamReader(uiTextBox1.Text, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                    BootloaderBUF = FileBootloader.ReadToEnd();//读取program文件
                    FileBootloader.Close();//关闭文件
                    FileBootloader.Dispose();//释放缓存
                }
                catch
                {
                    BootloaderBUF = null;
                    MessageBox.Show("无法读取Bootloader！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                StreamWriter streamWriter3 = new StreamWriter(uiTextBox1.Text);//创建写入流
                streamWriter3.Write(BootloaderBUF + ProgramFileBUF1);//合并并写入到文件中   
                streamWriter3.Flush();//刷新缓存
                streamWriter3.Close();//关闭流

                if (uiTextBox15.Text != "")//app2不为空时
                {

                    //读取合并后的boot与prgram1文件到缓存
                    try
                    {
                        //将boot文件读入缓存
                        StreamReader FileBootloader = new StreamReader(uiTextBox1.Text, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                        BootloaderBUF = FileBootloader.ReadToEnd();//读取program文件
                        FileBootloader.Close();//关闭文件
                        FileBootloader.Dispose();//释放缓存
                    }
                    catch
                    {
                        BootloaderBUF = null;
                        MessageBox.Show("无法读取Bootloader！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    //去掉boot文件中的文件结束帧
                    BootloaderBUF_CP = BootloaderBUF.Substring(0, (BootloaderBUF.Length - 13));//去掉最后一行13个字符

                    //合并并写入到原有boot文件中
                    StreamWriter streamWriter4 = new StreamWriter(uiTextBox1.Text);//创建写入流
                    streamWriter4.Write(BootloaderBUF_CP + ProgramFileBUF2);//合并并写入到文件中   
                    streamWriter4.Flush();//刷新缓存
                    streamWriter4.Close();//关闭流
                }

                //找到处理后的boot文件路径
                int num = uiTextBox1.Text.LastIndexOf(@"\");//找到最后一个“\”

                //将路径中的文件名去掉并写入新的文件名
                bootNowNameBUF = uiTextBox1.Text.Substring(0, num);//去掉路径的文件名
                bootNowNameBUF = bootNowNameBUF + @"\" + uiTextBox19.Text;//重命名合并后的文件
                //bootNowNameBUF = bootNowNameBUF + @"\Boot&Program.hex";

                try
                {
                    //移动并重命名
                    File.Move(uiTextBox1.Text, bootNowNameBUF);//文件重命名

                    //删除原来的program文件
                    FileInfo fileInfo = new FileInfo(uiTextBox10.Text);
                    fileInfo.Delete();//删除program程序文件

                    if (uiTextBox15.Text != "")//app2不为空时
                    {
                        //删除原来的program文件
                        FileInfo fileInfo1 = new FileInfo(uiTextBox15.Text);
                        fileInfo1.Delete();//删除program程序文件
                    }

                    //将处理后的文件显示在文本框中
                    StreamReader FileBootPRG = new StreamReader(bootNowNameBUF, System.Text.Encoding.GetEncoding("gb2312"));//创建读取流
                    uiRichTextBox1.Text = FileBootPRG.ReadToEnd();//读取program文件
                    FileBootPRG.Close();//关闭文件
                    FileBootPRG.Dispose();//释放缓存

                    MessageBox.Show("文件合并完成！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch
                {
                    MessageBox.Show("重命名失败或无法删除旧文件！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("文件路径不能为空！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void uiButton5_Click(object sender, EventArgs e)//退出按钮
        {
            System.Diagnostics.Process.GetCurrentProcess().Kill();
        }
    }
}
